﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using Deferred.Editor.Gui;
using Deferred.Library.Scene;
using Microsoft.Xna.Framework.Content;

namespace Deferred.Editor.Content
{
    public class ContentUpdater
    {
        private string baseDirectory;
        private List<string> contentItemPaths;
        private ContentBuilder builder;
        private Form window;
        private string currentSceneLocation;
        private SceneGraph currentScene;
        private ContentManager deferredContent;
        private BackgroundWorker backgroundBuildWorker = new BackgroundWorker();
        private ContentChooserWindow chooserWindow;

        public bool HasContent { get; private set; }
        public List<string> ContentItemPaths 
        {
            get { return contentItemPaths; }
            private set
            {
                contentItemPaths = value;
                chooserWindow.ContentItemPaths = contentItemPaths;
            }
        }
        public string BaseDirectory
        {
            get { return baseDirectory; }
            private set
            {
                baseDirectory = value;
                chooserWindow.BaseDirectory = baseDirectory;
            }
        }
        public SceneGraph CurrentScene
        {
            get { return currentScene; }
            private set
            {
                currentScene = value;
                if (CurrentSceneChanged != null)
                    CurrentSceneChanged(this, EventArgs.Empty);
            }
        }

        public EventHandler CurrentSceneChanged;
        public EventHandler OpenContentCompleted;

        public ContentUpdater(Form window, ContentManager deferredContent, ContentBuilder builder, ContentChooserWindow chooserWindow)
        {
            this.window = window;
            this.deferredContent = deferredContent;
            this.builder = builder;
            this.chooserWindow = chooserWindow;
            ContentItemPaths = new List<string>();
            backgroundBuildWorker.DoWork += new DoWorkEventHandler(openContentTask);
            backgroundBuildWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(openContentComplete);
            HasContent = false;
        }

        public bool SaveScene()
        {
            if (CurrentScene != null)
            {
                if (currentSceneLocation == null)
                {
                    return SaveSceneAs();
                }
                else
                {
                    SceneSerializer.writeSceneGraph(Path.Combine(baseDirectory, currentSceneLocation), CurrentScene);
                    return true;
                }
            }
            return true;
        }

        public bool SaveSceneAs()
        {
            chooserWindow.ValidExtensions = new List<string> { "scene" };
            chooserWindow.AllowNewDirectoriesAndFiles = true;

            if (DialogResult.OK == chooserWindow.ShowDialog(window))
            {
                currentSceneLocation = chooserWindow.SelectedFile;
                return SaveScene();
            }

            return false;
        }

        public bool PromptAndSaveScene()
        {
            if (CurrentScene != null)
            {
                DialogResult result = MessageBox.Show(window, "Would you like to save the current scene?", window.Text, MessageBoxButtons.YesNoCancel);
                if (DialogResult.OK == result)
                {
                    return SaveScene();
                }
                return DialogResult.Cancel != result;
            }
            return true;
        }

        public bool openContent()
        {
            if (PromptAndSaveScene())
            {
                clearScene();
                ContentItemPaths.Clear();
                HasContent = false;

                OpenFileDialog dialog = new OpenFileDialog();
                dialog.CheckFileExists = true;
                dialog.DefaultExt = ".contentproj";
                dialog.Filter = "Content Projects|*.contentproj";

                if (DialogResult.OK == dialog.ShowDialog())
                {
                    string filename = dialog.FileName;
                    BaseDirectory = filename.Remove(filename.LastIndexOf(Path.DirectorySeparatorChar));
                    backgroundBuildWorker.RunWorkerAsync(dialog.FileName);
                    return true;
                }
            }

            return false;
        }

        public void openContentComplete(object sender, RunWorkerCompletedEventArgs e)
        {
            string buildError = (string)e.Result;
            if (string.IsNullOrEmpty(buildError))
            {
                ContentItemPaths.AddRange(builder.Contents);
                
                HasContent = true;
            }
            else
            {
                MessageBox.Show(buildError, "Build Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            if (OpenContentCompleted != null) OpenContentCompleted(this, EventArgs.Empty);
        }

        public void createNewScene()
        {
            if (PromptAndSaveScene())
            {
                setScene(new SceneGraph(), null);
            }
        }

        public void openScene()
        {
            if (PromptAndSaveScene())
            {
                clearScene();
                chooserWindow.ValidExtensions = new List<string> { "scene" };
                chooserWindow.AllowNewDirectoriesAndFiles = false;

                if (DialogResult.OK == chooserWindow.ShowDialog())
                {
                    string file = chooserWindow.SelectedFile;
                    string name = file.Replace(Path.GetExtension(chooserWindow.SelectedFile), "");

                    setScene(deferredContent.Load<SceneGraph>(name), file);
                }
            }
        }

        public void closeScene()
        {
            if (PromptAndSaveScene())
            {
                clearScene();
            }
        }

        private void clearScene() { setScene(null, null); }

        private void setScene(SceneGraph scene, string location)
        {
            currentSceneLocation = location;
            CurrentScene = scene;
        }

        private void openContentTask(object sender, DoWorkEventArgs e)
        {
            string filename = e.Argument.ToString();

            e.Result = builder.Build(filename);
        }
    }
}
